﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Gemli.Collections;

namespace Gemli.Data
{
    /// <summary>
    /// Describes the selection and filters 
    /// to be used to collect entity data from a database.
    /// </summary>
    /// <typeparam name="TModel"></typeparam>
    public class DataModelQuery<TModel> : DataModelQuery where TModel : DataModel
    {
        /// <summary>
        /// Returns a <see cref="DataModelQueryCondition&lt;T&gt;"/> that contains
        /// an indexer and can be used to describe a comparison
        /// against the specified CLR property/field.
        /// <example><code>myQuery.WhereProperty["MyProperty"].IsEqualTo(3)</code>
        /// describes a condition where the database field that is mapped to the CLR
        /// property/field "MyProperty" is exactly equal to 3.</example>
        /// </summary>
        public new DataModelQueryCondition<TModel> WhereProperty
        {
            get
            {
                var ret = new DataModelQueryCondition<TModel>(
                    FieldMappingKeyType.ClrMember, this);
                return ret;
            }
        }
        /// <summary>
        /// Returns a <see cref="DataModelQueryCondition&lt;T&gt;"/> that contains
        /// an indexer and can be used to describe a comparison
        /// against the specified database column name.
        /// <example><code>myQuery.WhereMappedColumn["MyField"].IsEqualTo(3)</code>
        /// describes a condition where the value of the database column "MyField"
        /// is exactly equal to 3.</example>
        /// </summary>
        public new DataModelQueryCondition<TModel> WhereMappedColumn
        {
            get
            {
                var ret = new DataModelQueryCondition<TModel>(
                    FieldMappingKeyType.DbColumn, this);
                return ret;
            }
        }

        #region OrderBy / AddSortItem

        /// <summary>
        /// Adds a field to the OrderBy collection.
        /// The <paramref name="fieldName"/> parameter
        /// is assumed to be a CLR member name, not a DB
        /// column name.
        /// </summary>
        /// <param name="fieldName"></param>
        /// <returns></returns>
        public new DataModelQuery<TModel> AddSortItem(string fieldName)
        {
            return AddSortItem(fieldName, false);
        }

        /// <summary>
        /// Adds a field to the OrderBy collection.
        /// The <paramref name="fieldName"/> parameter
        /// is assumed to be a CLR member name, not a DB
        /// column name.
        /// </summary>
        /// <param name="fieldName"></param>
        /// <param name="sortDirection"></param>
        /// <returns></returns>
        public new DataModelQuery<TModel> AddSortItem(string fieldName, Sort sortDirection)
        {
            return AddSortItem(fieldName, false, sortDirection);
        }

        /// <summary>
        /// Adds a field to the OrderBy collection.
        /// </summary>
        /// <param name="fieldName"></param>
        /// <param name="matchOnDbColumn">
        /// If true, matches on the mapped DB column name 
        /// rather than the mapped CLR member name.
        /// </param>
        /// <returns></returns>
        public new DataModelQuery<TModel> AddSortItem(string fieldName, bool matchOnDbColumn)
        {
            return AddSortItem(fieldName, matchOnDbColumn, Sort.Ascending);
        }

        /// <summary>
        /// Adds a field to the OrderBy collection
        /// </summary>
        /// <param name="fieldName"></param>
        /// <param name="keyType"></param>
        /// <returns></returns>
        public new DataModelQuery<TModel> AddSortItem(string fieldName, FieldMappingKeyType keyType)
        {
            return AddSortItem(fieldName, keyType, Sort.Ascending);
        }

        /// <summary>
        /// Adds a field to the OrderBy collection.
        /// </summary>
        /// <param name="fieldName"></param>
        /// <param name="matchOnDbColumn">
        /// If true, matches on the mapped DB column name 
        /// rather than the mapped CLR member name.
        /// </param>
        /// <param name="sortOrder"></param>
        /// <returns></returns>
        public new DataModelQuery<TModel> AddSortItem(string fieldName, bool matchOnDbColumn, Sort sortOrder)
        {
            return (DataModelQuery<TModel>)base.AddSortItem(fieldName, matchOnDbColumn, sortOrder);
        }

        /// <summary>
        /// Adds a field to the OrderBy collection
        /// </summary>
        /// <param name="fieldName"></param>
        /// <param name="keyType"></param>
        /// <param name="sortOrder"></param>
        /// <returns></returns>
        public new DataModelQuery<TModel> AddSortItem(string fieldName, FieldMappingKeyType keyType, Sort sortOrder)
        {

            return (DataModelQuery<TModel>) base.AddSortItem(fieldName, keyType, sortOrder);
        }
        #endregion

    }
}
